﻿using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Xml;
using ilibrary.source.common;
using System.Net;
using System.Windows.Forms;

namespace ilibrary.source.model.metasearch
{
    public class ISBNDBSearcher : IDBSearchEngine
    {
        private BackgroundWorker backWorker = new BackgroundWorker();
        private ISearchHandler cb;
        private List<DBResult> results = new List<DBResult>();

        private int pageNumber;
        private int totalResults;
        private int pageSize;

        public ISBNDBSearcher()
        {
            pageNumber = 1;
            totalResults = 1;
            pageSize = 10;
        }


        public void searchFor(string query, int page_number, ISearchHandler callBack)
        {
            cb = callBack;
            pageNumber = page_number;

            //create a new back worker
            backWorker.Dispose();
            backWorker = new BackgroundWorker();
            backWorker.DoWork += new DoWorkEventHandler(DoWork);
            backWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(RunWorkerCompleted);
            backWorker.ProgressChanged += new ProgressChangedEventHandler(ProgressChanged);
            backWorker.WorkerReportsProgress = true;

            //run the search
            backWorker.RunWorkerAsync(query);
        }



        private void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {

            cb.searchDone(results, pageNumber, totalResults, pageSize);
        }

        private void DoWork(object sender, DoWorkEventArgs e)
        {

            doDBSearch((string)e.Argument);
        }

        private void ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            cb.searchProgressChanged(e.ProgressPercentage);
        }


        private void doDBSearch(string query)
        {
            BackgroundWorker bw = backWorker;
            //load result from isbndb
            string title = query;


            results.Clear();


            try
            {
                string url = "http://isbndb.com/api/books.xml?access_key=P6YIL8UC&results=texts,details&index1=full&value1=";
                foreach (string s in title.Split(Common.seps))
                {
                    if (s.Length > 0 && !s.Equals("&"))//ISBNDB.com seems to be having trouble with &
                        url += s + "+";
                }
                //remove trailing +
                url = url.Substring(0, url.Length - 1);
                //page number
                url += "&page_number=" + pageNumber;

                //encode url
                //url = HttpUtility.UrlEncode(url);


                WebClient client = new WebClient();


                XmlReader reader = XmlReader.Create(client.OpenRead(url));

                reader.MoveToContent();

                //get nb of results
                reader.ReadToFollowing("BookList");
                int total_results = int.Parse(reader.GetAttribute("total_results"));
                int page_number = int.Parse(reader.GetAttribute("page_number"));
                int page_size = int.Parse(reader.GetAttribute("page_size"));

                //disable more link if last set
                if (page_number * page_size >= total_results)
                    cb.enableNextLink(false);
                else cb.enableNextLink(true);
                if (page_number <= 1)
                    cb.enablePreviousLink(false);
                else cb.enablePreviousLink(true);

                totalResults = total_results;
                pageSize = page_size;
                pageNumber = page_number;

                while (reader.ReadToFollowing("BookData"))
                {
                    DBResult res = new DBResult();
                    res.db = "ISBNDB";

                    //isbn
                    while (reader.MoveToNextAttribute())
                    {
                        if (reader.Name == "isbn")
                            res.isbn = reader.Value;
                        else if (reader.Name == "book_id")
                            res.isbndbid = reader.Value;
                    }
                    reader.MoveToElement();
                    processBookData(reader.ReadSubtree(), res);
                    results.Add(res);
                    bw.ReportProgress(10); //10 is a dummy value. the progress will always be incremented by 10
                }
                reader.Close();
            }
            catch (Exception)
            {
                //results.Clear();
                MessageBox.Show("Unable to contact the remote web server.\r\nPlease, try again later.", "Connection Error");
                return;
            }
        }

        private void processBookData(XmlReader reader, DBResult res)
        {


            reader.ReadToFollowing("Title");
            res.title = reader.ReadString();

            reader.ReadToFollowing("TitleLong");
            res.titleLong = reader.ReadString();

            reader.ReadToFollowing("AuthorsText");
            res.authors = reader.ReadString();

            reader.ReadToFollowing("PublisherText");
            res.publisher = reader.ReadString();

            if (reader.ReadToFollowing("Details"))
                processBookDetails(reader, res);


            reader.ReadToFollowing("Summary");
            res.summary = Common.expandTags(reader.ReadString());




        }

        private void processBookDetails(XmlReader reader, DBResult tmp)
        {
            while (reader.MoveToNextAttribute())
            {
                if (reader.Name == "physical_description_text")
                    tmp.physical_description = reader.Value;
            }

        }

    }
}
